package com.anji.plus.gaea.curd.controller;


import com.anji.plus.gaea.annotation.AccessKey;
import com.anji.plus.gaea.annotation.DetailView;
import com.anji.plus.gaea.annotation.Permission;
import com.anji.plus.gaea.annotation.log.GaeaAuditLog;
import com.anji.plus.gaea.bean.ResponseBean;
import com.anji.plus.gaea.curd.dto.BaseDTO;
import com.anji.plus.gaea.curd.entity.BaseEntity;
import com.anji.plus.gaea.curd.entity.GaeaBaseEntity;
import com.anji.plus.gaea.curd.params.PageParam;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
import com.anji.plus.gaea.holder.UserContentHolder;
import com.anji.plus.gaea.utils.GaeaBeanUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.util.List;


/**
 * 基础controller
 *
 * @author lr
 * @since 2021-01-12
 */
public abstract class GaeaBaseController<P extends PageParam, T extends GaeaBaseEntity, D extends BaseDTO> extends BaseResponse {

    /**
     * 获取实际服务类
     *
     * @return
     */
    public abstract GaeaBaseService<P, T> getService();

    /**
     * 获取当前Controller数据库实体Entity
     *
     * @return
     */
    public abstract T getEntity();

    /**
     * 获取当前Controller数据传输DTO
     *
     * @return
     */
    public abstract D getDTO();

    /**
     * 分页模板
     *
     * @param param
     * @return
     */
    @GetMapping("/pageList")
    @Permission(code = "query", name = "查询")
    @GaeaAuditLog(pageTitle = "查询",isSaveResponseData = false)
    public ResponseBean pageList(P param) {
        IPage<T> iPage = getService().page(param);
        List<T> records = iPage.getRecords();

        //entity转换成DTO
        List<D> list = (List<D>)GaeaBeanUtils.copyList(records, getDTO().getClass());

        //处理dto返回结果
        pageResultHandler(list);
        Page<D> pageDto = new Page<>();
        pageDto.setCurrent(iPage.getCurrent())
                .setRecords(list)
                .setPages(iPage.getPages())
                .setTotal(iPage.getTotal())
                .setSize(iPage.getSize());
        return responseSuccessWithData(pageDto);
    }

    /**
     * 对分页dto返回处理
     * @param list
     * @return
     */
    public List<D> pageResultHandler(List<D> list) {
        return list;
    }

    /**
     * 对详情返回DTO进行处理
     * @param detail
     * @return
     */
    public D detailResultHandler(D detail) {
        return detail;
    }


    /**
     * 根据ID查询相关记录
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @Permission(code = "detail", name = "明细")
    @AccessKey
    @DetailView
    public ResponseBean detail(@PathVariable("id") Long id) {
        ///logger.info("{}根据ID查询服务开始，id为：{}", this.getClass().getSimpleName(), id);
        T result = getService().selectOne(id);
        D dto = getDTO();
        GaeaBeanUtils.copyAndFormatter(result, dto);
        //对返回值建处理
        detailResultHandler(dto);
        ResponseBean responseBean = responseSuccessWithData(resultDtoHandle(dto));
        logger.info("根据ID查询结束，req：{},res:{}", id,responseBean);
        return responseBean;
    }

    /**
     * 对明细结果进行处理,子类可以覆盖
     * @param d
     * @return
     */
    protected D resultDtoHandle(D d) {
        return d;
    }

    /**
     * 插入
     *
     * @param dto
     * @return
     * @throws Exception
     */
    @PostMapping
    @Permission(code = "insert", name = "新增")
    @GaeaAuditLog(pageTitle = "新增")
    public ResponseBean insert(@Validated @RequestBody D dto) {
        ///logger.info("{}新增服务开始，参数：{}", this.getClass().getSimpleName(), GaeaUtils.toJSONString(dto));
        T entity = getEntity();
        //dto转为数据库实体
        BeanUtils.copyProperties(dto, entity);
        //插入
        getService().insert(entity);

        ResponseBean ret = responseSuccessWithData(entity.copyTo(dto.getClass()));
        logger.info("新增服务结束，req：{},res:{}", dto,ret);
        return ret;
    }


    /**
     * 根据ID修改对饮记录
     *
     * @param dto
     * @return
     * @throws Exception
     */
    @PutMapping
    @Permission(code = "update", name = "修改")
    @GaeaAuditLog(pageTitle = "修改")
    public ResponseBean update(@Validated @RequestBody D dto) {
        String username = UserContentHolder.getContext().getUsername();
        T entity = getEntity();
        //dto转换entity
        BeanUtils.copyProperties(dto, entity);
        getService().update(entity);
        logger.info("更新服务结束，user:{},req:{},res:{}",username,dto,entity);
        ResponseBean ret = responseSuccessWithData(entity.copyTo(dto.getClass()));
        return ret;
    }


    /**
     * 根据ID删除指定记录,这里被删除的记录会进入删除记录表
     *
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    @Permission(code = "delete", name = "删除")
    @GaeaAuditLog(pageTitle = "删除")
    public ResponseBean deleteById(@PathVariable("id") Long id) {
        getService().deleteById(id);
        logger.info("删除服务结束:{}", id);
        return responseSuccess();
    }

    /**
     * 删除批量ID对应的记录
     *
     * @param ids
     * @return
     */
    @PostMapping("/delete/batch")
    @Permission(code = "deleteBatch", name = "批量删除")
    @GaeaAuditLog(pageTitle = "批量删除")
    public ResponseBean deleteBatchIds(@RequestBody List<Serializable> ids) {
        boolean deleteCount = getService().deleteByIds(ids);
        ResponseBean responseBean = responseSuccessWithData(deleteCount);
        logger.info("批量删除服务结束，req:{},ret：{}", ids, responseBean);
        return responseBean;
    }
}
